package com.iqismart.shorturl.exception;

import com.iqismart.shorturl.vo.base.Result;
import org.hibernate.exception.DataException;
import org.hibernate.exception.GenericJDBCException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.persistence.EntityNotFoundException;
import javax.servlet.http.HttpServletRequest;
import java.sql.SQLException;
import java.util.List;

/**
 * @Description
 * @Auther sty
 * @createTime 2019/10/14 01:40
 */

public class ExceptionTranslateHelper {
    private static final Logger log = LoggerFactory.getLogger(ExceptionTranslateHelper.class);

    public ExceptionTranslateHelper() {
    }

    public static Result translate(Exception exComing) {
        BaseException exOut = null;
        if (exComing instanceof UserTokenRequireException) {
            exOut = new BaseException(GlobalExceptionType.USER_TOKEN_REQUIRE);
        } else if (exComing instanceof BindException) {
            BindException bindException = (BindException)exComing;
            FieldError fieldError = bindException.getFieldError();
            StringBuilder sb = new StringBuilder();
            sb.append(fieldError.getField()).append("=[").append(fieldError.getRejectedValue()).append("]").append(fieldError.getDefaultMessage());
            exOut = new ClientParamValidException(sb.toString());
        } else {
            String localizedMessage;
            if (exComing instanceof MethodArgumentNotValidException) {
                MethodArgumentNotValidException validException = (MethodArgumentNotValidException)exComing;
                BindingResult bindingResult = validException.getBindingResult();
                List<FieldError> fieldErrors = bindingResult.getFieldErrors();
                if (fieldErrors != null && fieldErrors.size() > 0) {
                    localizedMessage = ((FieldError)fieldErrors.get(0)).getDefaultMessage();
                    String field = ((FieldError)fieldErrors.get(0)).getField();
                    exOut = new ClientParamValidException(localizedMessage);
                }
            } else if (exComing instanceof BaseException) {
                exOut = (BaseException)exComing;
            } else if (exComing instanceof DataException) {
                DataException dataException = (DataException)exComing;
                SQLException sqlException = dataException.getSQLException();
                exOut = new RepositoryException();
                ((BaseException)exOut).setDescription(dataException.getLocalizedMessage() + " because " + sqlException.getLocalizedMessage() + "(" + sqlException.getSQLState() + ")");
            } else {
                Throwable cause;
                SQLException sqlException;
                if (exComing instanceof JpaSystemException) {
                    JpaSystemException jpaSystemException = (JpaSystemException)exComing;
                    cause = jpaSystemException.getCause();
                    if (cause instanceof GenericJDBCException) {
                        sqlException = ((GenericJDBCException)cause).getSQLException();
                        localizedMessage = ((GenericJDBCException)cause).getLocalizedMessage();
                        exOut = new RepositoryException();
                        ((BaseException)exOut).setDescription(localizedMessage + " because " + sqlException.getLocalizedMessage() + "(" + sqlException.getSQLState() + ")");
                    } else {
                        exOut = new RepositoryException();
                        ((BaseException)exOut).setDescription(exComing.getLocalizedMessage());
                    }
                } else if (exComing instanceof DataIntegrityViolationException) {
                    DataIntegrityViolationException dataIntegrityViolationException = (DataIntegrityViolationException)exComing;
                    cause = dataIntegrityViolationException.getCause();
                    if (cause instanceof DataException) {
                        sqlException = ((DataException)cause).getSQLException();
                        exOut = new RepositoryException();
                        ((BaseException)exOut).setDescription(dataIntegrityViolationException.getLocalizedMessage() + " because " + sqlException.getLocalizedMessage() + "(" + sqlException.getSQLState() + ")");
                    } else {
                        exOut = new RepositoryException();
                        ((BaseException)exOut).setDescription(exComing.getLocalizedMessage());
                    }
                } else if (exComing instanceof HttpRequestMethodNotSupportedException) {
                    HttpRequestMethodNotSupportedException exception = (HttpRequestMethodNotSupportedException)exComing;
                    exOut = new BaseException(GlobalExceptionType.OTHER.code, exComing.getMessage(), exComing.getLocalizedMessage());

                    try {
                        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                        StringBuffer requestURL = request.getRequestURL();
                        log.error(requestURL.toString());
                    } catch (Exception var7) {
                        var7.printStackTrace();
                    }

                    log.error(exception.getMessage());
                } else if (exComing instanceof EntityNotFoundException) {
                    exOut = new BaseException(GlobalExceptionType.ENTITY_NOT_FOUND_EXCEPTION);
                } else if (exComing instanceof HttpMessageNotReadableException) {
                    exOut = new BaseException(GlobalExceptionType.CLIENT_PARAM_VALID_FAILD.code, GlobalExceptionType.CLIENT_PARAM_VALID_FAILD.message, exComing.getMessage());
                } else {
                    exOut = new BaseException(GlobalExceptionType.OTHER.code, exComing.getMessage(), exComing.getMessage());
                    exComing.printStackTrace();
                }
            }
        }

        return new Result((BaseException)exOut);
    }
}

